package com.phychips.rcp;

public class Rcp9200 implements iRcp {
    // private RcpPacket rcpPacket = null;
    @Override
    public boolean setReaderPowerManagement(RcpPacket rcpPacket, int sleepmode) {
        int payload_len = 1;
        RcpException exception;

        try {
            if ((sleepmode != RcpConst.SLEEP)
                    && (sleepmode != RcpConst.DEEPSLEEP)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);

                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_CTL_RD_PWR, payload_len, true);

            RcpLib.convertIntToByteArray(sleepmode, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Get basic information from the reader.
     *
     * @param argument : Model (0x00), S/N (0x01), Manufacturer (0x02), Frequency
     *                 (0x03), Tag Type (0x04)
     * @return false;
     */
    @Override
    public boolean getReaderInfo(RcpPacket rcpPacket, int type) {
        int payload_len = 1;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_RD_INFO, payload_len, true);
            RcpLib.convertIntToByteArray(type, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Get the current region. PR9200 uses individual channel table that depends
     * on region.
     *
     * @return false;
     */
    @Override
    public boolean getRegion(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_REGION, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Set the current region. PR9200 uses individual channel table that depends
     * on region.
     *
     * @param region : Korea (0x11), US (0x21), Europe (0x31), Japan (0x41), China1
     *               (0x51), China2 (0x52)
     * @return false;
     */
    @Override
    public boolean setRegion(RcpPacket rcpPacket, int region) {
        int payload_len = 1;
        RcpException exception;

        try {
            if (region != RcpConst.REGION_KOREA && region != RcpConst.REGION_US
                    && region != RcpConst.REGION_EU
                    && region != RcpConst.REGION_JAPAN
                    && region != RcpConst.REGION_CHINA1
                    && region != RcpConst.REGION_CHINA2) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_REGION, payload_len, true);
            RcpLib.convertIntToByteArray(region, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Set the system level reset.
     *
     * @return false;
     */
    @Override
    public boolean resetReader(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_CTL_RESET, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Get 18000-6C air interface protocol command ��Select�� parameters.
     *
     * @return false;
     */
    @Override
    public boolean getTypeCSelectParam(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_C_SEL_PARAM, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Set 18000-6C air interface protocol command ��Select�� parameters.
     *
     * @param param RcpTypeCSelect (target, action, memory bank, pointer, length,
     *              truncate, mask)
     * @return false;
     */
    @Override
    public boolean setTypeCSelectParam(RcpPacket rcpPacket, RcpTypeCSelect param) {
        int payload_len = param.length + 7;
        int number;
        RcpException exception;

        try {
            if ((param.target != RcpConst.INVENTORY_S0
                    && param.target != RcpConst.INVENTORY_S1
                    && param.target != RcpConst.INVENTORY_S2
                    && param.target != RcpConst.INVENTORY_S3 && param.target != RcpConst.INVENTORY_SL)
                    || (param.memoryBank != RcpConst.MB_EPC
                    && param.memoryBank != RcpConst.MB_RFU
                    && param.memoryBank != RcpConst.MB_TID && param.memoryBank != RcpConst.MB_USER)
                    || (param.truncate != RcpConst.TRUC_ENABLE && param.truncate != RcpConst.TRUC_DISABLE)
                    || (param.length != param.mask.length)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_C_SEL_PARAM, payload_len, true);

            // encode payload
            number = (((param.target << 5) + param.action) << 2)
                    + param.memoryBank;
            RcpLib.convertIntToByteArray(number, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);
            RcpLib.convertLongToByteArray(param.pointer, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 4);
            RcpLib.convertIntToByteArray(param.length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 5, 1);
            number = param.truncate << 7;
            RcpLib.convertIntToByteArray(number, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, 1);
            RcpLib.copyByteArray(param.mask, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 7, param.mask.length);

            rcpPacket.endEncodePacket();

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Get 18000-6C air interface protocol command ��Query�� parameters.
     *
     * @return false;
     */
    @Override
    public boolean getTypeCQueryParam(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_C_QRY_PARAM, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Set 18000-6C air interface protocol command ��Query�� parameters.
     *
     * @param param : RcpTypeCQuery (DR, M, TRext, Sel, Session, Target, slots)
     * @return false;
     */
    @Override
    public boolean setTypeCQueryParam(RcpPacket rcpPacket, RcpTypeCQuery param) {
        int payload_len = 2;
        int number;
        RcpException exception;

        try {

            if ((param.queryDR != RcpConst.DR81 && param.queryDR != RcpConst.DR643)
                    || (param.queryM < 0 || param.queryM > 3)
                    || (param.trext != RcpConst.NO_PILOT && param.trext != RcpConst.PILOT)
                    || (param.sel < RcpConst.SEL_ALL1 || param.sel > RcpConst.SEL_SL)
                    || (param.session < RcpConst.SESSION_S0 || param.session > RcpConst.SESSION_S3)
                    || (param.target != RcpConst.TARGET_A && param.target != RcpConst.TARGET_B)
                    || (param.slot_num < RcpConst.MIN_SLOT || param.slot_num > RcpConst.MAX_SLOT)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_C_QRY_PARAM, payload_len, true);

            // encode payload
            number = (param.queryDR << 7) | (param.queryM << 5)
                    | (param.trext << 4) | (param.sel << 2) | param.session;
            RcpLib.convertIntToByteArray(number, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);
            number = (param.target << 7) | (param.slot_num << 3);
            RcpLib.convertIntToByteArray(number, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 1);

            rcpPacket.endEncodePacket();

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Get RF channel. This command is valid only for non-FH mode.
     *
     * @return false;
     */
    @Override
    public boolean getCurrChannel(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_CH, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Set RF channel. This command is valid only for non-FHSS mode.
     *
     * @param param : RcpChannelInfo (channel number, channel offset)
     * @return false;
     */
    @Override
    public boolean setCurrChannel(RcpPacket rcpPacket, RcpChannelInfo param) {
        int payload_len = 2;
        RcpException exception;

        try {
            if ((param.channel_num < 0 || param.channel_num > 255)
                    || (param.channel_offset < 0 || param.channel_offset > 255)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_CH, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(param.channel_num, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);
            RcpLib.convertIntToByteArray(param.channel_offset,
                    rcpPacket.packet, RcpPacket.PAYLOAD_INDEX + 1, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public boolean getSession(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_SESSION, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public boolean setSession(RcpPacket rcpPacket, int session) {
        int payload_len = 1;
        RcpException exception;

        try {
            if (session < 0 || session > 4) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_SESSION, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(session, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }


    /**
     * Get FH and LBT control
     *
     * @return false;
     */
    @Override
    public boolean getFhLbtParam(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_FH_LBT, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Set FH and LBT Parameters
     *
     * @param param : RcpFhLbtParam (read time, idle time, carrier sense time, RF
     *              power level, FH, LBT, CW)
     * @return false;
     */
    @Override
    public boolean setFhLbtParam(RcpPacket rcpPacket, RcpFhLbtParam param) {
        int payload_len = 0x0B;
        RcpException exception;

        try {
            if ((param.readtime < 0 || param.readtime > 0xFFFF)
                    || (param.idletime < 0 || param.idletime > 0xFFFF)
                    || (param.sensetime < 0 || param.sensetime > 0xFFFF)
                    || (param.powerlevel < 0 || param.powerlevel > 0xFFFF)
                    || (param.fhmode != RcpConst.FH_ENABLE && param.fhmode != RcpConst.FH_DISABLE)
                    || (param.lbtmode != RcpConst.LBT_ENABLE && param.lbtmode != RcpConst.LBT_DISABLE)
                    || (param.cwmode != RcpConst.CW_ENABLE && param.cwmode != RcpConst.CW_DISABLE)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_FH_LBT, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(param.readtime, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 2);
            RcpLib.convertIntToByteArray(param.idletime, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2, 2);
            RcpLib.convertIntToByteArray(param.sensetime, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.convertIntToByteArray(param.powerlevel, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, 2);
            RcpLib.convertIntToByteArray(param.fhmode, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 8, 1);
            RcpLib.convertIntToByteArray(param.lbtmode, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 9, 1);
            RcpLib.convertIntToByteArray(param.cwmode, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 10, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Get Output power level.
     *
     * @return false;
     */
    @Override
    public boolean getOutputPowerLevel(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_TX_PWR, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Set current Tx power level.
     *
     * @param power_level : PR9200 Power
     * @return false;
     */
    @Override
    public boolean setOutputPowerLevel(RcpPacket rcpPacket, byte power_level) {
        int payload_len = 2;
        // RcpException exception;

        // if (power_level < 20 || power_level > 25)
        // {
        // exception = new RcpException("invalid argument",
        // RcpConst.INVALID_ARGUMENT);
        // throw exception;
        // }
        byte[] source = new byte[2];
        source[0] = 0x00;
        source[1] = power_level;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_TX_PWR, payload_len, true);

            // encode payload
            RcpLib.copyByteArray(source, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, source.length);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Turn the Continuous Wave (CW) signal on/off. This command packet is only
     * valid for idle mode.
     *
     * @param control : On (0xFF), Off (0x00)
     * @return false;
     */
    @Override
    public boolean setRfCw(RcpPacket rcpPacket, int control) {
        int payload_len = 1;
        RcpException exception;

        try {
            if (control != RcpConst.CW_SIG_ON && control != RcpConst.CW_SIG_OFF) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_CTL_CW, payload_len, true);

            RcpLib.convertIntToByteArray(control, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Read Type C user data from specified memory bank.
     *
     * @param param : RcpTypeCTag (EPC length, EPC, starting address, data length)
     * @return false;
     */
    @Override
    public boolean ReadTypeCUserData(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception;

        try {
            if ((param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.epc_length > param.epc.length)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            payload_len = param.epc_length + 6;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_READ_C_USER_DT, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2, param.epc_length);
            RcpLib.convertIntToByteArray(param.start_address, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2 + param.epc_length, 2);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4 + param.epc_length, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Read Type C tag data from specified memory bank.
     *
     * @param RcpTypeCTag (password, EPC length, EPC, memory bank, starting address,
     *                    data length)
     * @return false;
     */
    @Override
    public boolean readFromTagMemory(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception;

        try {
            if ((param.password < 0 || param.password > 0xFFFFFFFFL)
                    || (param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.memory_bank != RcpConst.MB_EPC
                    && param.memory_bank != RcpConst.MB_RFU
                    && param.memory_bank != RcpConst.MB_TID && param.memory_bank != RcpConst.MB_USER)
                    || (param.start_address < 0 || param.start_address > 0xFFFF)
                    || (param.data_length < 0 || param.data_length > 0xFFFF)
                    || (param.epc_length > param.epc.length)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            payload_len = param.epc_length + 11;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_READ_C_DT, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);
            RcpLib.convertIntToByteArray(param.memory_bank, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6 + param.epc_length, 1);
            RcpLib.convertIntToByteArray(param.start_address, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 7 + param.epc_length, 2);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 9 + param.epc_length, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Get current frequency hopping table.
     *
     * @return false;
     */
    @Override
    public boolean getFreqHoppingTable(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_HOPPING_TBL, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Start an automatic tag read operation, tag IDs are sent back to user
     * though notification packet.
     *
     * @param reserve      : type B tag (0x01), type C Tag (0x02)
     * @param max_tags     : maximum number of tag to read
     * @param max_time     : maximum elapsed time to tagging (sec)
     * @param repeat_cycle : Repeat cycle (how many times reader perform inventory
     *                     round).
     * @return false;
     */
    @Override
    public boolean startReadTags(RcpPacket rcpPacket, int max_tags,
                                 int max_time, int repeat_cycle) {
        int payload_len = 5;
        int reserve = 0x02;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_STRT_AUTO_READ_EX, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(reserve, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 0, 1);
            RcpLib.convertIntToByteArray(max_tags, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 1);
            RcpLib.convertIntToByteArray(max_time, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2, 1);
            RcpLib.convertIntToByteArray(repeat_cycle, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 3, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean startReadTagsWithRssi(RcpPacket rcpPacket, int max_tags,
                                         int max_time, int repeat_cycle) {
        int payload_len = 5;
        int reserve = 0x02;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_START_AUTO_READ_RSSI, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(reserve, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 0, 1);
            RcpLib.convertIntToByteArray(max_tags, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 1);
            RcpLib.convertIntToByteArray(max_time, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2, 1);
            RcpLib.convertIntToByteArray(repeat_cycle, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 3, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean startReadTagsWithTid(RcpPacket rcpPacket, int max_tags,
                                        int max_time, int repeat_cycle) {
        int payload_len = 5;
        int reserve = 0x02;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_READ_C_UII_TID, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(reserve, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 0, 1);
            RcpLib.convertIntToByteArray(max_tags, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 1);
            RcpLib.convertIntToByteArray(max_time, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2, 1);
            RcpLib.convertIntToByteArray(repeat_cycle, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 3, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean startReadTagsEx2(RcpPacket rcpPacket, int cmd, int rssi,
                                    int ant, int max_tags, int max_time, int repeat_cycle) {
        int payload_len = 7;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_STRT_AUTO_READ_EX2, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(cmd, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 0, 1);
            RcpLib.convertIntToByteArray(rssi, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 1);
            RcpLib.convertIntToByteArray(ant, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 2, 1);
            RcpLib.convertIntToByteArray(max_tags, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 3, 1);
            RcpLib.convertIntToByteArray(max_time, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 1);
            RcpLib.convertIntToByteArray(repeat_cycle, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 5, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Stop an automatic read2 operation.
     *
     * @return false;
     */
    @Override
    public boolean stopReadTags(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_STOP_AUTO_READ_EX, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Write type C tag data.
     *
     * @param param : RcpTypeCTag (password, EPC length, EPC, memory bank,
     *              starting address, data length, data)
     * @return false;
     */
    @Override
    public boolean writeToTagMemory(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception;

        try {
            if ((param.password < 0 || param.password > 0xFFFFFFFFL)
                    || (param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.memory_bank != RcpConst.MB_EPC
                    && param.memory_bank != RcpConst.MB_RFU
                    && param.memory_bank != RcpConst.MB_TID && param.memory_bank != RcpConst.MB_USER)
                    || (param.start_address < 0 || param.start_address > 0xFFFF)
                    || (param.data_length < 0 || param.data_length > 0xFFFF)
                    || (param.epc_length > param.epc.length)
                    || (param.data_length > param.data.length)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            payload_len = param.epc_length + param.data_length * 2 + 11;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_WRITE_C_DT, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);
            RcpLib.convertIntToByteArray(param.memory_bank, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6 + param.epc_length, 1);
            RcpLib.convertIntToByteArray(param.start_address, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 7 + param.epc_length, 2);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 9 + param.epc_length, 2);
            RcpLib.copyByteArray(param.data, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 11 + param.epc_length,
                    param.data_length * 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * Block write type C tag data.
     *
     * @param param : RcpTypeCTag (password, EPC length, EPC, memory bank,
     *              starting address, data length, data)
     * @return false;
     */
    @Override
    public boolean blockwriteToTagMemory(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception;

        try {
            if ((param.password < 0 || param.password > 0xFFFFFFFFL)
                    || (param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.memory_bank != RcpConst.MB_EPC
                    && param.memory_bank != RcpConst.MB_RFU
                    && param.memory_bank != RcpConst.MB_TID && param.memory_bank != RcpConst.MB_USER)
                    || (param.start_address < 0 || param.start_address > 0xFFFF)
                    || (param.data_length < 0 || param.data_length > 0xFFFF)
                    || (param.epc_length > param.epc.length)
                    || (param.data_length > param.data.length)) {
                exception = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception;
            }

            payload_len = param.epc_length + param.data_length * 2 + 11;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_BLOCKWRITE_C_DT, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);
            RcpLib.convertIntToByteArray(param.memory_bank, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6 + param.epc_length, 1);
            RcpLib.convertIntToByteArray(param.start_address, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 7 + param.epc_length, 2);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 9 + param.epc_length, 2);
            RcpLib.copyByteArray(param.data, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 11 + param.epc_length,
                    param.data_length * 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Block erases type C tag data.
     *
     * @param param : RcpTypeCTag (password, EPC length, EPC, memory bank,
     *              starting address, data length)
     * @return false;
     */
    @Override
    public boolean blockeraseTagMemory(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception2;

        try {
            if ((param.password < 0 || param.password > 0xFFFFFFFFL)
                    || (param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.memory_bank != RcpConst.MB_EPC
                    && param.memory_bank != RcpConst.MB_RFU
                    && param.memory_bank != RcpConst.MB_TID && param.memory_bank != RcpConst.MB_USER)
                    || (param.start_address < 0 || param.start_address > 0xFFFF)
                    || (param.epc_length > param.epc.length)) {
                exception2 = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception2;
            }

            payload_len = param.epc_length + 11;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_BLOCKERASE_C_DT, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);
            RcpLib.convertIntToByteArray(param.memory_bank, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6 + param.epc_length, 1);
            RcpLib.convertIntToByteArray(param.start_address, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 7 + param.epc_length, 2);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 9 + param.epc_length, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Kill a Tag.
     *
     * @param param : RcpTypeCTag (password, EPC length, EPC, recom)
     * @return false;
     */
    @Override
    public boolean killTag(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception3;

        try {
            if ((param.password < 0 || param.password > 0xFFFFFFFFL)
                    || (param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.recom < 0 || param.recom > 0xFF)
                    || (param.epc_length > param.epc.length)) {
                exception3 = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                // exception = new
                // RcpException(Long.toHexString(param.password),
                // RcpConst.INVALID_ARGUMENT);
                throw exception3;
            }

            payload_len = param.epc_length + 6;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_KILL_RECOM_C, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Lock an indicated memory bank in the tag.
     *
     * @param param : RcpTypeCTag (password, EPC length, EPC, Lock mask and action
     *              flags)
     * @return false;
     */
    @Override
    public boolean lockTagMemory(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;
        RcpException exception2;

        try {
            if ((param.password < 0 || param.password > 0xFFFFFFFFL)
                    || (param.epc_length < 0 || param.epc_length > 0xFFFF)
                    || (param.lock_mask < 0 || param.lock_mask > 0x0FFFFF)
                    || (param.epc_length > param.epc.length)) {
                exception2 = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception2;
            }

            payload_len = param.epc_length + 9;

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_LOCK_C, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);
            RcpLib.convertIntToByteArray(param.lock_mask, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6 + param.epc_length, 3);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Get current temperature.
     *
     * @return false;
     */
    @Override
    public boolean getTemperature(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_TEMPERATURE, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Get RSSI level
     *
     * @return false;
     */
    @Override
    public boolean getRssi(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_RSSI, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Scan RSSI level on all channels.
     *
     * @return false;
     */
    @Override
    public boolean scanRssi(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SCAN_RSSI, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean testReader(RcpPacket rcpPacket, int type) {
        int payload_len = 1;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_LEAKAGE_RSSI, payload_len, true);

            RcpLib.convertIntToByteArray(type, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Sets Registry Update function
     *
     * @param action : Store (0x01)
     * @return false;
     */
    @Override
    public boolean updateRegistry(RcpPacket rcpPacket, int action) {
        short payload_len = 1;
        RcpException exception2;

        try {
            if (action != RcpConst.STORE) {
                exception2 = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception2;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_UPDATE_REGISTRY, payload_len, true);

            RcpLib.convertIntToByteArray(action, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Sets Registry Erase function.
     *
     * @param action : Erase (0xFF)
     * @return false;
     */
    @Override
    public boolean eraseRegistry(RcpPacket rcpPacket, int action) {
        int payload_len = 1;
        RcpException exception2;

        try {
            if (action != RcpConst.ERASE) {
                exception2 = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception2;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_ERASE_REGISTRY, payload_len, true);

            RcpLib.convertIntToByteArray(action, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Gets Registry items.
     *
     * @param item : Registry Version (0x0000), Firmware Date (0x0001), Band
     *             (0x0002), Tx power (0x0003), FH/LBT (0x0004), Anti-collision
     *             Mode (0x0005), Modulation Mode (0x0006), Query(Q) (0x0007),
     *             Frequency Hopping Table (0x0008), Tx Power Table (0x0009)
     * @return false;
     */
    @Override
    public boolean getRegistry(RcpPacket rcpPacket, int item) {
        int payload_len = 2;
        RcpException exception2;

        try {
            if (item < RcpConst.REGISTRY_VERSION
                    || item > RcpConst.TX_POWER_TABLE) {
                exception2 = new RcpException("invalid argument",
                        RcpConst.INVALID_ARGUMENT);
                throw exception2;
            }

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_GET_REGISTRY_ITEM, payload_len, true);

            RcpLib.convertIntToByteArray(item, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 2);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Get Tx Power Table.
     *
     * @return false;
     */
    @Override
    public boolean getOutputPowerTable(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.GET_POWER_TABLE, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * This directly send the command packet to RFID reader. It returns the
     * response packet in byte array. Auto read / stop are not supported.
     *
     * @param packet : command packet
     * @return false;
     */
    @Override
    public boolean nativeRcp(RcpPacket rcpPacket, byte[] packet) {
        int payload_len;
        byte code;
        RcpException exception2;

        try {
            payload_len = RcpLib.convertByteArrayToInt(packet, 3, 2);
            code = packet[2];
            // rcpPacket = RcpPacket.getInstance();

            if (code == RcpConst.RCP_CMD_STRT_AUTO_READ
                    || code == RcpConst.RCP_CMD_STRT_AUTO_READ_EX
                    || code == RcpConst.RCP_CMD_STOP_AUTO_READ
                    || code == RcpConst.RCP_CMD_STOP_AUTO_READ_EX) {
                exception2 = new RcpException(
                        "auto read is not supported in native API",
                        RcpConst.NATIVE_NOT_SUPPORT);
                throw exception2;
            }

            rcpPacket.checkPacketSize(payload_len, true);

            RcpLib.copyByteArray(packet, 0, rcpPacket.packet, 0, packet.length);
            rcpPacket.endEncodePacket();
            rcpPacket.checkValidPacket();

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Authentication.
     *
     * @return false;
     */
    public boolean authentication(RcpPacket rcpPacket, boolean itemLevel, byte[] ich, byte[] tag) {
        // rcpPacket = RcpPacket.getInstance();

        StringBuffer sb = new StringBuffer();

        byte TagH = (byte) ((tag.length >> 8) & 0xff);
        byte TagL = (byte) (tag.length & 0xff);
        byte SendRep = 0x01;
        byte IncRepLen = 0x01;
        byte csi = 0x00;
        byte LenH = 0x00;
        byte LenL = 0x78;
        byte AuthMeth = 0x00;
        byte CusData = 0x01;
        byte RFU = 0x00;
        byte keyID = 0x01;
        byte profile = 0x00;
        int offset = 0x00;
        byte BlockCount = 0x01;
        byte ProtMode = 0x01;

        if (itemLevel) {
            LenL = 0x60;
            CusData = 0x00;
            keyID = 0x00;

            sb.append(RcpLib.byte2string(TagH));
            sb.append(RcpLib.byte2string(TagL));
            sb.append(RcpLib.byte2str(tag));
            sb.append(RcpLib.byte2string(SendRep));
            sb.append(RcpLib.byte2string(IncRepLen));
            sb.append(RcpLib.byte2string(csi));
            sb.append(RcpLib.byte2string(LenH));
            sb.append(RcpLib.byte2string(LenL));
            sb.append(RcpLib.byte2string((byte) ((AuthMeth << 6) | (CusData << 5) | RFU)));
            sb.append(RcpLib.byte2string(keyID));
            sb.append(RcpLib.byte2str(ich));
        } else {
            sb.append(RcpLib.byte2string(TagH));
            sb.append(RcpLib.byte2string(TagL));
            sb.append(RcpLib.byte2str(tag));
            sb.append(RcpLib.byte2string(SendRep));
            sb.append(RcpLib.byte2string(IncRepLen));
            sb.append(RcpLib.byte2string(csi));
            sb.append(RcpLib.byte2string(LenH));
            sb.append(RcpLib.byte2string(LenL));
            sb.append(RcpLib.byte2string((byte) ((AuthMeth << 6) | (CusData << 5) | RFU)));
            sb.append(RcpLib.byte2string(keyID));
            sb.append(RcpLib.byte2str(ich));
            sb.append(RcpLib.byte2string((byte) ((profile << 4) | (offset >> 8))));
            sb.append(RcpLib.byte2string((byte) (offset & 0xff)));
            sb.append(RcpLib.byte2string((byte) ((BlockCount << 4) | (ProtMode & 0x0f))));
        }

        byte[] code = RcpLib.convertStringToByteArray(sb.toString());

        try {
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_AUTHENTICATE, code.length, true);
            RcpLib.copyByteArray(code, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, code.length);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Authentication.
     *
     * @return false;
     */
    public boolean authenticationEx(RcpPacket rcpPacket, boolean itemLevel, byte[] ich, byte[] tag) {
        // rcpPacket = RcpPacket.getInstance();

        StringBuffer sb = new StringBuffer();

        byte MB = 0x02;
        byte TagH = (byte) ((tag.length >> 8) & 0xff);
        byte TagL = (byte) (tag.length & 0xff);
        byte SendRep = 0x01;
        byte IncRepLen = 0x01;
        byte csi = 0x00;
        byte LenH = 0x00;
        byte LenL = 0x78;
        byte AuthMeth = 0x00;
        byte CusData = 0x01;
        byte RFU = 0x00;
        byte keyID = 0x01;
        byte profile = 0x00;
        int offset = 0x00;
        byte BlockCount = 0x01;
        byte ProtMode = 0x01;

        if (itemLevel) {
            LenL = 0x60;
            CusData = 0x00;
            keyID = 0x00;

            sb.append(RcpLib.byte2string(MB));
            sb.append(RcpLib.byte2string(TagH));
            sb.append(RcpLib.byte2string(TagL));
            sb.append(RcpLib.byte2str(tag));
            sb.append(RcpLib.byte2string(SendRep));
            sb.append(RcpLib.byte2string(IncRepLen));
            sb.append(RcpLib.byte2string(csi));
            sb.append(RcpLib.byte2string(LenH));
            sb.append(RcpLib.byte2string(LenL));
            sb.append(RcpLib.byte2string((byte) ((AuthMeth << 6)
                    | (CusData << 5) | RFU)));
            sb.append(RcpLib.byte2string(keyID));
            sb.append(RcpLib.byte2str(ich));
        } else {
            sb.append(RcpLib.byte2string(MB));
            sb.append(RcpLib.byte2string(TagH));
            sb.append(RcpLib.byte2string(TagL));
            sb.append(RcpLib.byte2str(tag));
            sb.append(RcpLib.byte2string(SendRep));
            sb.append(RcpLib.byte2string(IncRepLen));
            sb.append(RcpLib.byte2string(csi));
            sb.append(RcpLib.byte2string(LenH));
            sb.append(RcpLib.byte2string(LenL));
            sb.append(RcpLib.byte2string((byte) ((AuthMeth << 6)
                    | (CusData << 5) | RFU)));
            sb.append(RcpLib.byte2string(keyID));
            sb.append(RcpLib.byte2str(ich));
            sb.append(RcpLib
                    .byte2string((byte) ((profile << 4) | (offset >> 8))));
            sb.append(RcpLib.byte2string((byte) (offset & 0xff)));
            sb.append(RcpLib
                    .byte2string((byte) ((BlockCount << 4) | (ProtMode & 0x0f))));
        }

        byte[] code = RcpLib.convertStringToByteArray(sb.toString());

        try {
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_AUTHENTICATE_EX, code.length, true);
            RcpLib.copyByteArray(code, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, code.length);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Untraceable.
     *
     * @return false;
     */
    public boolean untraceable(RcpPacket rcpPacket, byte[] password, byte[] tag, byte uflag, byte epc, byte tid, byte user, byte range) {
        // rcpPacket = RcpPacket.getInstance();

        StringBuffer sb = new StringBuffer();

        byte TagH = (byte) ((tag.length >> 8) & 0xff);
        byte TagL = (byte) (tag.length & 0xff);

        sb.append(RcpLib.byte2str(password));
        sb.append(RcpLib.byte2string(TagH));
        sb.append(RcpLib.byte2string(TagL));
        sb.append(RcpLib.byte2str(tag));
        sb.append(RcpLib.byte2string(uflag));
        sb.append(RcpLib.byte2string(epc));
        sb.append(RcpLib.byte2string(tid));
        sb.append(RcpLib.byte2string(user));
        sb.append(RcpLib.byte2string(range));

        byte[] code = RcpLib.convertStringToByteArray(sb.toString());

        try {
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_UNTRACEABLE, code.length, true);
            RcpLib.copyByteArray(code, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, code.length);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * Untraceable.
     *
     * @return false;
     */
    public boolean untraceableEx(RcpPacket rcpPacket, byte[] password, byte[] tag, byte uflag, byte epc, byte tid, byte user, byte range) {
        // rcpPacket = RcpPacket.getInstance();

        StringBuffer sb = new StringBuffer();

        byte MB = 0x02;
        byte TagH = (byte) ((tag.length >> 8) & 0xff);
        byte TagL = (byte) (tag.length & 0xff);

        sb.append(RcpLib.byte2str(password));
        sb.append(RcpLib.byte2string(MB));
        sb.append(RcpLib.byte2string(TagH));
        sb.append(RcpLib.byte2string(TagL));
        sb.append(RcpLib.byte2str(tag));
        sb.append(RcpLib.byte2string(uflag));
        sb.append(RcpLib.byte2string(epc));
        sb.append(RcpLib.byte2string(tid));
        sb.append(RcpLib.byte2string(user));
        sb.append(RcpLib.byte2string(range));

        byte[] code = RcpLib.convertStringToByteArray(sb.toString());

        try {
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_UNTRACEABLE_EX, code.length, true);
            RcpLib.copyByteArray(code, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, code.length);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean getBeep(RcpPacket rcpPacket) {
        int payload_len = 0;

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_GET_BEEP, payload_len, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean setBeep(RcpPacket rcpPacket, boolean state) {
        int payload_len = 1;
        byte[] data = new byte[payload_len];

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_SET_BEEP, payload_len, true);

            if (state) {
                data[0] = (byte) 0x01;
            } else {
                data[0] = (byte) 0x00;
            }
            // encode payload
            RcpLib.copyByteArray(data, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, payload_len);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean calGpAdc(RcpPacket rcpPacket, int min, int max) {
        int payload_len = 2;
        byte[] data = new byte[payload_len];

        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_CAL_GPADC, payload_len, true);

            data[0] = (byte) (min & 0xff);
            data[1] = (byte) (max & 0x00);

            RcpLib.copyByteArray(data, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, payload_len);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;

    }

    @Override
    public boolean FERtest(RcpPacket rcpPacket) {
        try {
            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_FER_TEST, 0, true);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean loopBackTest(RcpPacket rcpPacket) {
        final byte loopbackPayload = (byte) 0xAA;
        byte[] temp = new byte[20];

        for (int i = 0; i < temp.length; i++) {
            temp[i] = (byte) loopbackPayload;
        }

        try {

            // rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_PACKET_TEST, temp.length, true);

            RcpLib.copyByteArray(temp, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, temp.length);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean waveTest(RcpPacket rcpPacket, int data) {
        byte[] temp = new byte[2];

        temp[0] = (byte) (0xff); // test mode
        temp[1] = (byte) (data & 0xff);

        try {
            // rcpPacket = RcpPacket.getInstance();

            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD, (byte) 0xAE,
                    temp.length, true);

            RcpLib.copyByteArray(temp, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, temp.length);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean readLongTag(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;

        try {
            // rcpPacket = RcpPacket.getInstance();
            payload_len = param.epc_length + 11;

            rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_READ_C_DT_EX, payload_len, true);

            // encode payload
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 4);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 4, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6, param.epc_length);
            RcpLib.convertIntToByteArray(param.memory_bank, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 6 + param.epc_length, 1);
            RcpLib.convertIntToByteArray(param.start_address, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 7 + param.epc_length, 2);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 9 + param.epc_length, 2);

            rcpPacket.endEncodePacket();

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean genericTransport(RcpPacket rcpPacket, RcpTypeCTag param) {
        int payload_len;

        try {
            payload_len = param.epc_length + ((param.data_length + 7) >> 3)
                    + 10;

            rcpPacket = RcpPacket.getInstance();
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_TRANSPORT, payload_len, true);

            // encode payload
            RcpLib.convertIntToByteArray(param.ts, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, 1);
            RcpLib.convertLongToByteArray(param.password, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1, 4);
            RcpLib.convertIntToByteArray(param.rm, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1 + 4, 1);
            RcpLib.convertIntToByteArray(param.epc_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1 + 4 + 1, 2);
            RcpLib.copyByteArray(param.epc, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1 + 4 + 1 + 2, param.epc_length);
            RcpLib.convertIntToByteArray(param.data_length, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1 + 4 + 1 + 2 + param.epc_length,
                    2);
            RcpLib.copyByteArray(param.data, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX + 1 + 4 + 1 + 2 + param.epc_length
                            + 2, (param.data_length + 7) >> 3);

            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean readSignature(RcpPacket rcpPacket, byte[] password, byte[] tag, byte ptr, byte cnt) {
        // rcpPacket = RcpPacket.getInstance();

        StringBuffer sb = new StringBuffer();

        byte TagH = (byte) ((tag.length >> 8) & 0xff);
        byte TagL = (byte) (tag.length & 0xff);

        sb.append(RcpLib.byte2str(password));
        sb.append(RcpLib.byte2string(TagH));
        sb.append(RcpLib.byte2string(TagL));
        sb.append(RcpLib.byte2str(tag));
        sb.append(RcpLib.byte2string(ptr));
        sb.append(RcpLib.byte2string(cnt));

        byte[] code = RcpLib.convertStringToByteArray(sb.toString());

        try {
            rcpPacket.startEncodePacket(RcpConst.RCP_MSG_CMD,
                    RcpConst.RCP_CMD_READSIGNATURE, code.length, true);
            RcpLib.copyByteArray(code, 0, rcpPacket.packet,
                    RcpPacket.PAYLOAD_INDEX, code.length);
            rcpPacket.endEncodePacket();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }


}
